package com.xbd.wxpay.controller;

import com.alibaba.fastjson.JSONObject;
import com.xbd.wxpay.util.SM4Util;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping("/info")
public class InfoController {
    /**
     * 字符集固定 utf-8
     */
    public  static   String ENCODING = "utf-8";
    /**
     * 接入 appid
     */
    public   String appid = "OP00000733";

    public String term_no ="F0166806";
    /**
     * 商户证书序列号，和商户私钥对应
     */
    public   String mchSerialNo = "822290058120N51";

    public String serial_no="00dfba8194c41b84cf";
    public static String SCHEMA = "LKLAPI-SHA256withRSA";

    //分隔符
    public static  String       MARK_SUBTRACTION                = "-";
    //分隔符
    public static  String       MARK_COMMA                      = ",";
    //分隔符
    public static  String       MARK_EQUEL                      = "=";

    private  final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private  final SecureRandom RANDOM = new SecureRandom();
    private String getJarFilePath() {
        ApplicationHome home = new ApplicationHome(getClass());
        File jarFile = home.getSource();
        return jarFile.getParentFile().toString();
    }

    protected String generateNonceStr() {
        char[] nonceChars = new char[32];
        for (int index = 0; index < nonceChars.length; ++index) {
            nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
        }
        return new String(nonceChars);
    }
    protected long generateTimestamp() {
        return System.currentTimeMillis() / 1000;
    }

    public String sign(byte[] message, PrivateKey privateKey) {
        try {
            Signature sign = Signature.getInstance("SHA256withRSA");
            sign.initSign(privateKey);
            sign.update(message);
            return new String(Base64.encodeBase64(sign.sign()));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持SHA256withRSA", e);
        } catch (SignatureException e) {
            throw new RuntimeException("签名计算失败", e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException("无效的私钥", e);
        }
    }
    public  String getAuthorization(String nonceStr,long timestamp,String body) throws IOException {


        String message = appid + "\n" + serial_no + "\n" + timestamp + "\n" + nonceStr + "\n" + body + "\n";

        //System.out.println("getToken message :  " + message);

        File file= new File(getClass().getClassLoader().getResource("static/OP00000003_private_key.pem").getFile());
        PrivateKey merchantPrivateKey = loadPrivateKey(new FileInputStream(file));

        String signature = this.sign(message.getBytes(ENCODING), merchantPrivateKey);

        String authorization = "appid=\"" + appid + "\"," + "serial_no=\"" + serial_no + "\"," + "timestamp=\""
                + timestamp + "\"," + "nonce_str=\"" + nonceStr + "\"," + "signature=\"" + signature + "\"";
      //  System.out.println("authorization message :" + authorization);

        return authorization;
    }



    @RequestMapping(method = RequestMethod.GET,value = "/info")
    public String info() throws Exception {

        long timestamp =generateTimestamp();
        String nonceStr = generateNonceStr();



        JSONObject jsonObject  = new JSONObject();
        jsonObject.put("version","1.0");
        jsonObject.put("orderNo","FD660E1FAA3A4470933CDEDAE1EC1D02");
        jsonObject.put("orgCode","1");
        jsonObject.put("merCupNo",mchSerialNo);



        Date now = new Date();
        // 创建日期时间格式化器
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
        // 将日期时间对象格式化为字符串
        String formattedDateTime = formatter.format(now);
        JSONObject body  = new JSONObject();

        body.put("reqData",jsonObject);
        body.put("reqId","KFPT20230223181747812863750");
        body.put("version","2.0");
        body.put("reqTime",formattedDateTime);


        System.out.println(body.toJSONString());
        String apiUrl = "https://test.wsmsd.cn/sit/api/v2/mms/openApi/ledger/queryLedgerMer";

        String str = body.toJSONString();




        String authorization = getAuthorization(nonceStr,timestamp,str);
        System.out.println("authorization"+authorization);
        HttpResponse response = post(apiUrl , str, authorization);


        HttpEntity entity = response.getEntity();

        if (entity != null) {
            // 将响应实体转换为字符串
            String responseBody = EntityUtils.toString(entity, StandardCharsets.UTF_8);

            System.out.println("ff"+responseBody);
            // 打印输出响应体
            return  responseBody;
        }else{
            return  "";
        }
    }


    public  HttpResponse post(String url, String message, String authorization) throws Exception {
        SSLContext ctx = SSLContext.getInstance("TLS");
        X509TrustManager tm = new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
            public void checkClientTrusted(X509Certificate[] xcs, String str) {}
            public void checkServerTrusted(X509Certificate[] xcs, String str) {}
        };
        HttpClient http = new DefaultHttpClient();
        ClientConnectionManager ccm = http.getConnectionManager();
        ctx.init(null, new TrustManager[] { tm }, null);
        SSLSocketFactory ssf = new SSLSocketFactory(ctx);
        ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        SchemeRegistry registry = ccm.getSchemeRegistry();
        registry.register(new Scheme("https", ssf,443));
        HttpPost post = new HttpPost(url);
        StringEntity myEntity = new StringEntity(message, ENCODING);
        post.setEntity(myEntity);
        getAuthorizationMap(SCHEMA + " " + authorization);
        post.setHeader("Authorization", SCHEMA + " " + authorization);
        post.setHeader("Accept", "application/json");
        post.setHeader("Content-Type", "application/json");
        return http.execute(post);
    }

    public static Map<String, String> getAuthorizationMap(String authorization) {
        Map<String, String> map = new HashMap<>();
        authorization = authorization.trim();
        int bpos = authorization.indexOf(" ");
        String authType = authorization.substring(0, bpos);
        String []typeArr = authType.split(MARK_SUBTRACTION);
        if(typeArr.length >1) {
            map.put("signAlgorithm", typeArr[1]);
        }
        if (typeArr.length > 2) {
            map.put("encryptAlgorithm", typeArr[2]);
        }
        String signInfo = authorization.substring(bpos + 1);
        String[] infoArr = signInfo.split(MARK_COMMA);
        for (String info : infoArr) {
            if (info.contains(MARK_EQUEL)) {
                int fpos = info.indexOf(MARK_EQUEL);
                String value = info.substring(fpos+1).trim();
                value = value.substring(1,value.length()-1);//去掉双引号
                map.put(info.substring(0,fpos).trim(),value);
            }
        }
        //System.out.println(map.toString());
        return map;
    }

    public static PrivateKey loadPrivateKey(InputStream inputStream) {
        try {
            ByteArrayOutputStream array = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int length;
            while ((length = inputStream.read(buffer)) != -1) {
                array.write(buffer, 0, length);
            }

            String privateKey = array.toString("utf-8").replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "").replaceAll("\\s+", "");
            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        } catch (IOException e) {
            throw new RuntimeException("无效的密钥");
        }
    }

    public static X509Certificate loadCertificate(InputStream inputStream) {
        try {
            CertificateFactory cf = CertificateFactory.getInstance("X509");
            X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream);

            cert.checkValidity();
            return cert;
        } catch (CertificateExpiredException e) {
            throw new RuntimeException("证书已过期", e);
        } catch (CertificateNotYetValidException e) {
            throw new RuntimeException("证书尚未生效", e);
        } catch (CertificateException e) {
            throw new RuntimeException("无效的证书", e);
        }
    }
}
